#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <asm/atomic.h>
#include <linux/xlog.h>

#include "kd_camera_hw.h"

#include "kd_imgsensor.h"
#include "kd_imgsensor_define.h"
#include "kd_camera_feature.h"

/////////////
#include <mach/upmu_common.h>
#include <mach/upmu_common_sw.h>
#include <mach/upmu_sw.h>
#include <mach/upmu_hw.h>
#include "../../../../../imgsensor/src/mt6735m/twcam.h"


/******************************************************************************
 * Debug configuration
******************************************************************************/
#define PFX "[kd_camera_hw]"
#define PK_DBG_NONE(fmt, arg...)    do {} while (0)
#define PK_DBG_FUNC(fmt, arg...)    xlog_printk(ANDROID_LOG_INFO, PFX , fmt, ##arg)

#define DEBUG_CAMERA_HW_K
#ifdef DEBUG_CAMERA_HW_K
#define PK_DBG PK_DBG_FUNC
#define PK_ERR(fmt, arg...)         xlog_printk(ANDROID_LOG_ERROR, PFX , fmt, ##arg)
#define PK_XLOG_INFO(fmt, args...) \
                do {    \
                   xlog_printk(ANDROID_LOG_INFO, PFX , fmt, ##arg); \
                } while(0)
#else
#define PK_DBG(a,...)
#define PK_ERR(a,...)
#define PK_XLOG_INFO(fmt, args...)
#endif

/*
#ifndef BOOL
typedef unsigned char BOOL;
#endif
*/

/* Mark: need to verify whether ISP_MCLK1_EN is required in here //Jessy @2014/06/04*/
extern void ISP_MCLK1_EN(BOOL En);
#define MODULE_SUPPORT_MAX   64

int cntVCAMD =0;
int cntVCAMA =0;
int cntVCAMIO =0;
int cntVCAMAF =0;
int cntVCAMD_SUB =0;

static DEFINE_SPINLOCK(kdsensor_pw_cnt_lock);
#define IDX_PS_CMRST 0
#define IDX_PS_CMPDN 4
#define IDX_PS_MODE 1
#define IDX_PS_ON   2
#define IDX_PS_OFF  3

u32 pinSet[3][8] = {
                        //for main sensor
                     {  CAMERA_CMRST_PIN, // The reset pin of main sensor uses GPIO10 of mt6306, please call mt6306 API to set
                        CAMERA_CMRST_PIN_M_GPIO,   /* mode */
                        GPIO_OUT_ONE,              /* ON state */
                        GPIO_OUT_ZERO,             /* OFF state */
                        CAMERA_CMPDN_PIN,
                        CAMERA_CMPDN_PIN_M_GPIO,
                        GPIO_OUT_ONE,
                        GPIO_OUT_ZERO,
                     },
                     //for sub sensor
                     {  CAMERA_CMRST1_PIN,
                        CAMERA_CMRST1_PIN_M_GPIO,
                        GPIO_OUT_ONE,
                        GPIO_OUT_ZERO,
                        CAMERA_CMPDN1_PIN,
                        CAMERA_CMPDN1_PIN_M_GPIO,
                        GPIO_OUT_ONE,
                        GPIO_OUT_ZERO,
                     },
                     //for main_2 sensor
                     {  GPIO_CAMERA_INVALID,
                        GPIO_CAMERA_INVALID,   /* mode */
                        GPIO_OUT_ONE,               /* ON state */
                        GPIO_OUT_ZERO,              /* OFF state */
                        GPIO_CAMERA_INVALID,
                        GPIO_CAMERA_INVALID,
                        GPIO_OUT_ONE,
                        GPIO_OUT_ZERO,
                     }
                   };

static UINT32 PowerID[2][4] = {
	{
		CAMERA_POWER_VCAM_IO,
		CAMERA_POWER_VCAM_A,
		SUB_CAMERA_POWER_VCAM_D,
		CAMERA_POWER_VCAM_AF
	},
	{
		CAMERA_POWER_VCAM_IO,
		CAMERA_POWER_VCAM_A,
		SUB_CAMERA_POWER_VCAM_D,
		CAMERA_POWER_VCAM_AF
	}
};

bool _hwPowerOn(MT65XX_POWER powerId, int powerVolt, char *mode_name){

	if( hwPowerOn( powerId,  powerVolt, mode_name))
	{
	    spin_lock(&kdsensor_pw_cnt_lock);
		if(powerId==CAMERA_POWER_VCAM_D)
			cntVCAMD+= 1;
		else if(powerId==CAMERA_POWER_VCAM_IO)
			cntVCAMIO+= 1;
		else if(powerId==CAMERA_POWER_VCAM_AF)
			cntVCAMAF+= 1;
		else if(powerId==SUB_CAMERA_POWER_VCAM_D)
			cntVCAMD_SUB+= 1;
		spin_unlock(&kdsensor_pw_cnt_lock);
		return true;
	}
	return false;
}

bool _hwPowerDown(MT65XX_POWER powerId, char *mode_name){

	if( hwPowerDown( powerId, mode_name))
	{
	    spin_lock(&kdsensor_pw_cnt_lock);
		if(powerId==CAMERA_POWER_VCAM_D)
			cntVCAMD-= 1;
		else if(powerId==CAMERA_POWER_VCAM_IO)
			cntVCAMIO-= 1;
		else if(powerId==CAMERA_POWER_VCAM_AF)
			cntVCAMAF-= 1;
		else if(powerId==SUB_CAMERA_POWER_VCAM_D)
			cntVCAMD_SUB-= 1;
		spin_unlock(&kdsensor_pw_cnt_lock);
		return true;
	}
	return false;
}

void checkPowerBeforClose( char* mode_name)
{

	int i= 0;

	PK_DBG("[checkPowerBeforClose]cntVCAMD:%d, cntVCAMA:%d,cntVCAMIO:%d, cntVCAMAF:%d, cntVCAMD_SUB:%d,\n",
		cntVCAMD, cntVCAMA,cntVCAMIO,cntVCAMAF,cntVCAMD_SUB);


	for(i=0;i<cntVCAMD;i++)
		hwPowerDown(CAMERA_POWER_VCAM_D,mode_name);
	for(i=0;i<cntVCAMIO;i++)
		hwPowerDown(CAMERA_POWER_VCAM_IO,mode_name);
	for(i=0;i<cntVCAMAF;i++)
		hwPowerDown(CAMERA_POWER_VCAM_AF,mode_name);
	for(i=0;i<cntVCAMD_SUB;i++)
		hwPowerDown(SUB_CAMERA_POWER_VCAM_D,mode_name);

	 cntVCAMD =0;
	 cntVCAMA =0;
	 cntVCAMIO =0;
	 cntVCAMAF =0;
	 cntVCAMD_SUB =0;

}

enum FOCUS_TYPE {
	FT_FF,//fixed focus
	FT_AF,//auto focus
	FT_MAX
};

enum PIN_LEVEL {
	PL_LOW,
	PL_HIGH
};

enum  POWER_SEQ_PIN_NAME{
         MPOWER_DOWN_PIN=1,
         MRESET_PIN,
         SPOWER_DOWN_PIN,
         SRESET_PIN,
		  IOVDD_PIN, 
		  AVDD_PIN, 
		  DVDD_PIN, 
		  AF_PIN,
         SEQ_END
};

struct powerctrl {
	enum POWER_SEQ_PIN_NAME           pwtype;
	UINT32                    voltage;//enum MT65XX_POWER_VOLTAGE voltage;
	UINT32                    nms;
};

struct power_seq {
	char *name;
	enum FOCUS_TYPE ftype;
	struct powerctrl *pwon;
	struct powerctrl *pwoff;
	//enum POWERDOWN_RESET_STATE_TYPE work_by_powerdown_state;
	//enum POWERDOWN_RESET_STATE_TYPE work_by_reset_state;
	//enum POWERDOWN_RESET_STATE_TYPE close_by_powerdown_state;
	//enum POWERDOWN_RESET_STATE_TYPE close_by_reset_state;
};

#define SEQ_SIZE 20

struct powerctrl Main_camera_PowerOn[SEQ_SIZE];
struct powerctrl Main_camera_PowerOff[SEQ_SIZE];
struct power_seq Main_ModulePower[2];
struct powerctrl Sub_camera_PowerOn[SEQ_SIZE];
struct powerctrl Sub_camera_PowerOff[SEQ_SIZE];
struct power_seq Sub_ModulePower[2];

struct powerctrl Sub_camera_DefaultPowerOn[SEQ_SIZE];
struct powerctrl Sub_camera_DefaultPowerOff[SEQ_SIZE];
struct power_seq Sub_DefaultModulePower[2];
struct power_seq Main_DefaultModulePower[2];

void camera_set_power_info_value(struct powerctrl *camera_Power, int power_pin_name,int power_state,int delay_value,int idex)
{
   camera_Power[idex].pwtype = power_pin_name;
   camera_Power[idex].voltage= power_state * 1000;
   camera_Power[idex].nms = delay_value;
}

int sub_camera_index_num = 0;
int main_camera_index_num = 0;
char list_end[]="the_list_end";

int camera_set_power_ctrl(char *main_name, struct powerctrl *camera_Power, char *power_seq_str)
{
	unsigned short *para_buff=NULL;
	int count;
	int power_pin_name=0;
	int power_state=0;
	int delay_value=0;
	int i, j;
	
	count = hwinfo_parser_refers(main_name, power_seq_str, &para_buff);
	if((count==0)||(count== -1)) {
		printk("your hwinfo not have camera_sensor_power_on_seq title will be set default value \n");
		return -1;
	}
	printk("[@@debug] count = %d\n", count);
	
	for (j=0,i=0;j<count;para_buff++) {
		power_pin_name = *para_buff++;j++;
		power_state= *para_buff++;j++;
		delay_value=*para_buff;j++;
		printk("[@@debug] power_pin_name = %d, power_state = %d, delay_value = %d, i = %d, j = %d\n", power_pin_name, power_state, delay_value, i , j);
		camera_set_power_info_value(camera_Power,power_pin_name,power_state,delay_value,i);
		i++;					  
	}	
	return 0;
}

struct power_seq* get_camera_power_seq(char *currSensorName, CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx)
{
   	int count=0;
	char main_key[20];
	int ret = -1;

	if(SensorIdx == DUAL_CAMERA_MAIN_SENSOR) {
		sprintf(main_key, "main_cam_para%d", main_camera_index_num);
		printk("[@@debug] main_key = %s\n", main_key);
		ret = camera_set_power_ctrl(main_key, Main_camera_PowerOn, "power_on_seq");
		if(ret) {
			printk("get main camera power on sequence error\n");
			return 0;
		}
		ret = camera_set_power_ctrl(main_key, Main_camera_PowerOff, "power_off_seq");
		if(ret) {
			printk("get main camera power off sequence error\n");
			return 0;
		}
		
		Main_ModulePower[0].name=currSensorName;
		Main_ModulePower[1].name=list_end;
		Main_ModulePower[0].ftype=FT_AF;
		Main_ModulePower[1].ftype=FT_AF;
		Main_ModulePower[0].pwon=Main_camera_PowerOn;
		Main_ModulePower[0].pwoff=Main_camera_PowerOff;
		Main_ModulePower[1].pwon=NULL;
		Main_ModulePower[1].pwoff=NULL;	
		return Main_ModulePower;
    } 
	else if(SensorIdx==DUAL_CAMERA_SUB_SENSOR) {
		sprintf(main_key, "sub_cam_para%d", sub_camera_index_num);
		printk("[@@debug] main_key = %s\n", main_key);
    	ret = camera_set_power_ctrl(main_key, Sub_camera_PowerOn, "power_on_seq");
		if(ret) {
			printk("get sub camera power on sequence error\n");
			return 0;
		}
		ret = camera_set_power_ctrl(main_key, Sub_camera_PowerOff, "power_off_seq");
		if(ret) {
			printk("get sub camera power off sequence error\n");
			return 0;
		}

		Sub_ModulePower[0].name=currSensorName;
		Sub_ModulePower[1].name=list_end;
		Sub_ModulePower[0].ftype=FT_AF;
		Sub_ModulePower[1].ftype=FT_AF;
		Sub_ModulePower[0].pwon=Sub_camera_PowerOn;
		Sub_ModulePower[0].pwoff=Sub_camera_PowerOff;
		Sub_ModulePower[1].pwon=NULL;
		Sub_ModulePower[1].pwoff=NULL;	
		return Sub_ModulePower;
    }  
}

int get_sub_camera_power_seq(char *currSensorName)
{
	int count=0;
	char main_key[20];
	u32 i ,j= 0;
	unsigned short *para_buff=NULL;
	int power_pin_name=0;
	int power_state=0;
	int delay_value=0;
	
	sprintf(main_key, "sub_cam_para%d", sub_camera_index_num);
	printk("[@@debug] main_key = %s\n", main_key);
	
	count = hwinfo_parser_refers(main_key,"camera_sensor_power_on_seq", &para_buff);
	if((count==0)||(count== -1)) {
		printk("your hwinfo not have camera_sensor_power_on_seq title will be set default value \n");
		return -1;
	}
	printk("[@@debug] count = %d\n", count);
	
	for (j=0,i=0;j<count;para_buff++) {
		power_pin_name = *para_buff++;j++;
		power_state= *para_buff++;j++;
		delay_value=*para_buff;j++;
		printk("[@@debug] power_pin_name = %d, power_state = %d, delay_value = %d, i = %d, j = %d\n", power_pin_name, power_state, delay_value, i , j);
		camera_set_power_info_value(Sub_camera_PowerOn,power_pin_name,power_state,delay_value,i);
		i++;					  
	}		 
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	count = hwinfo_parser_refers(main_key,"camera_sensor_power_off_seq", &para_buff);
	if((count==0)||(count== -1)) {
		printk("your hwinfo not have camera_sensor_power_off_seq title will be set default value \n");
		return -1;
	}
	printk("[@@debug] @count = %d\n", count);
	for (j=0,i=0;j<count;para_buff++) {
		power_pin_name = *para_buff++;j++;
		power_state= *para_buff++;j++;
		delay_value=*para_buff;j++;
		printk("[@@debug] @power_pin_name = %d, power_state = %d, delay_value = %d, i = %d, j = %d\n", power_pin_name, power_state, delay_value, i , j);
		camera_set_power_info_value(Sub_camera_PowerOff, power_pin_name, power_state, delay_value, i);
		i++;					  
	}	
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	Sub_ModulePower[0].name=currSensorName;
	Sub_ModulePower[1].name=list_end;
	Sub_ModulePower[0].ftype=FT_AF;
	Sub_ModulePower[1].ftype=FT_AF;
	Sub_ModulePower[0].pwon=Sub_camera_PowerOn;
	Sub_ModulePower[0].pwoff=Sub_camera_PowerOff;
	Sub_ModulePower[1].pwon=NULL;
	Sub_ModulePower[1].pwoff=NULL;
	return 0;	   
}

static BOOL kdPinPdnRstCtrl(struct powerctrl *power, UINT32 On) {
	//u32 pinSetIdx = SensorIdx;  //default main sensor
	enum POWER_SEQ_PIN_NAME ptype;
	
//    printk("[@@debug]%s: enter------SensorIdx = %d\n", __FUNCTION__, SensorIdx);
    
	if(NULL == power) {
		return FALSE;
	}
	
    //printk("[@@debug]%s: pinSetIdx = %d\n", __FUNCTION__, pinSetIdx);
    ptype = power->pwtype;
    if(GPIO_CAMERA_INVALID != pinSet[0][IDX_PS_CMRST]) {
		if(ptype == MPOWER_DOWN_PIN) { 
			if(mt_set_gpio_mode(pinSet[0][IDX_PS_CMPDN], pinSet[0][IDX_PS_CMPDN+IDX_PS_MODE])){PK_DBG("[CAMERA LENS] set PWDN gpio mode failed!! \n");}
			if(mt_set_gpio_dir(pinSet[0][IDX_PS_CMPDN], GPIO_DIR_OUT)){PK_DBG("[CAMERA LENS] set PWDN gpio dir failed!! \n");}
		
			if(On) {
				printk("[@@debug]%s: set mpwdn High\n", __FUNCTION__);
				printk("[@@@debug]%s: set mpwdn High\n", __FUNCTION__);
				if(mt_set_gpio_out(pinSet[0][IDX_PS_CMPDN], pinSet[0][IDX_PS_CMPDN+IDX_PS_ON])){PK_DBG("[CAMERA LENS] set PWDN gpio on failed!! \n");}
			}
			else {
				printk("[@@debug]%s: set mpwdn Low\n", __FUNCTION__);
				printk("[@@@debug]%s: set mpwdn Low\n", __FUNCTION__);
				if(mt_set_gpio_out(pinSet[0][IDX_PS_CMPDN], pinSet[0][IDX_PS_CMPDN+IDX_PS_OFF])){PK_DBG("[CAMERA LENS] set PWDN gpio off failed!! \n");}
			}
		}
		else if (ptype == MRESET_PIN) {
			if(mt_set_gpio_mode(pinSet[0][IDX_PS_CMRST], pinSet[0][IDX_PS_CMRST+IDX_PS_MODE])){PK_DBG("[CAMERA LENS] set RST gpio mode failed!! \n");}
			if(mt_set_gpio_dir(pinSet[0][IDX_PS_CMRST], GPIO_DIR_OUT)){PK_DBG("[CAMERA LENS] set RST gpio dir failed!! \n");}
		
			if(On) {
				printk("[@@debug]%s: set mrst High\n", __FUNCTION__);
				printk("[@@@debug]%s: set mrst High\n", __FUNCTION__);
				if(mt_set_gpio_out(pinSet[0][IDX_PS_CMRST], pinSet[0][IDX_PS_CMRST+IDX_PS_ON])){PK_DBG("[CAMERA LENS] set RST gpio on failed!! \n");}
			}
			else {
				printk("[@@debug]%s: set mrst Low\n", __FUNCTION__);
				printk("[@@@debug]%s: set mrst Low\n", __FUNCTION__);
				if(mt_set_gpio_out(pinSet[0][IDX_PS_CMRST], pinSet[0][IDX_PS_CMRST+IDX_PS_OFF])){PK_DBG("[CAMERA LENS] set RST gpio off failed!! \n");}
			}
		}
		else if (ptype == SPOWER_DOWN_PIN) {
			if(mt_set_gpio_mode(pinSet[1][IDX_PS_CMRST], pinSet[1][IDX_PS_CMRST+IDX_PS_MODE])){PK_DBG("[CAMERA LENS] set RST gpio mode failed!! \n");}
			if(mt_set_gpio_dir(pinSet[1][IDX_PS_CMRST], GPIO_DIR_OUT)){PK_DBG("[CAMERA LENS] set RST gpio dir failed!! \n");}
		
			if(On) {
				printk("[@@debug]%s: set spwdn High\n", __FUNCTION__);
				printk("[@@@debug]%s: set spwdn High\n", __FUNCTION__);
				if(mt_set_gpio_out(pinSet[1][IDX_PS_CMRST], pinSet[1][IDX_PS_CMRST+IDX_PS_ON])){PK_DBG("[CAMERA LENS] set RST gpio on failed!! \n");}
			}
			else {
				printk("[@@debug]%s: set spwdn Low\n", __FUNCTION__);
				printk("[@@@debug]%s: set spwdn Low\n", __FUNCTION__);
				if(mt_set_gpio_out(pinSet[1][IDX_PS_CMRST], pinSet[1][IDX_PS_CMRST+IDX_PS_OFF])){PK_DBG("[CAMERA LENS] set RST gpio off failed!! \n");}
			}
		}
		else if (ptype == SRESET_PIN) {
			if(mt_set_gpio_mode(pinSet[1][IDX_PS_CMRST], pinSet[1][IDX_PS_CMRST+IDX_PS_MODE])){PK_DBG("[CAMERA LENS] set RST gpio mode failed!! \n");}
			if(mt_set_gpio_dir(pinSet[1][IDX_PS_CMRST], GPIO_DIR_OUT)){PK_DBG("[CAMERA LENS] set RST gpio dir failed!! \n");}
		
			if(On) {
				printk("[@@debug]%s: set srst High\n", __FUNCTION__);
				printk("[@@@debug]%s: set srst High\n", __FUNCTION__);
				if(mt_set_gpio_out(pinSet[1][IDX_PS_CMRST], pinSet[1][IDX_PS_CMRST+IDX_PS_ON])){PK_DBG("[CAMERA LENS] set RST gpio on failed!! \n");}
			}
			else {
				printk("[@@debug]%s: set srst Low\n", __FUNCTION__);
				printk("[@@@debug]%s: set srst Low\n", __FUNCTION__);
				if(mt_set_gpio_out(pinSet[1][IDX_PS_CMRST], pinSet[1][IDX_PS_CMRST+IDX_PS_OFF])){PK_DBG("[CAMERA LENS] set RST gpio off failed!! \n");}
			}
		}
		
		if(power->nms > 0) {
			if(power->nms & 0x1000) {
				msleep(power->nms & 0x0fff);
			}
			else {
				mdelay(power->nms & 0x0fff);
			}
		}
		
		return TRUE;
	}
	
	return FALSE;
}

static BOOL kdPinPowerCtrl(u32 SensorIdx, struct powerctrl *power, BOOL On, char* mode_name) {
	UINT32 id = 0;
	BOOL ret = TRUE;
	UINT32 level = 0;
	
    printk("[@@debug]%s: enter, SensorIdx = %d\n", __FUNCTION__, SensorIdx);
    
	if(NULL == power) {
		return FALSE;
	}
	
	printk("[@@debug]%s: power->pwtype = %d, power->voltage = %d\n", __FUNCTION__, power->pwtype, power->voltage);
	
	if(power->pwtype > SEQ_END) {
		return FALSE;
	}
	
	switch(power->pwtype) {
		case MPOWER_DOWN_PIN:
		case MRESET_PIN:
		case SPOWER_DOWN_PIN:
		case SRESET_PIN:
			if(power->voltage) {
				level = 1;
			}
			else {
				level = 0;
			}
			
			ret = kdPinPdnRstCtrl(power, level);
			break;
		case IOVDD_PIN:
		case AVDD_PIN:
		case DVDD_PIN:
		case AF_PIN:
			
			//if(power->pwtype == PWT_AF) {
			//	;//////////////////////////////////////////////
			//}
			
			id = power->pwtype - IOVDD_PIN;
			
			if(On) {
				printk("[@@@debug]%s SensorIdx = %d, id = %d, power->voltage = %d, mode_name = %s\n", __FUNCTION__, SensorIdx, id, power->voltage, mode_name);
				if(TRUE != _hwPowerOn(PowerID[SensorIdx][id], power->voltage, mode_name)) {
					printk("[@@debug][CAMERA SENSOR] Fail to enable IO power\n");
					return FALSE;
				}

				printk("[@@@debug] %s CAMERA_POWER_VCAM_AF VOL_2800 \n", __FUNCTION__);
				if(TRUE != _hwPowerOn(CAMERA_POWER_VCAM_AF, VOL_2800,mode_name)) {
					printk("[@@debug][CAMERA SENSOR] Fail to enable AF power\n");
					return FALSE;
				}
			}
			else {
				printk("[@@@debug]%s SensorIdx = %d, id = %d, mode_name = %s\n", __FUNCTION__, SensorIdx, id, mode_name);
				if(TRUE != _hwPowerDown(PowerID[SensorIdx][id], mode_name))
				{
					printk("[@@debug][CAMERA SENSOR] Fail to disable IO power\n");
					return FALSE;
				}

			        if(TRUE != _hwPowerDown(CAMERA_POWER_VCAM_AF,mode_name))
               {
                   printk("[@@debug][CAMERA SENSOR] Fail to disable AF power\n");
                   return FALSE;
               }
			}
			
			if(power->nms > 0) {
				if(power->nms & 0x1000) {
					msleep(power->nms & 0x0fff);
				}
				else {
					mdelay(power->nms & 0x0fff);
				}
			}
			ret = TRUE;
			break;
		default:
			break;
	}
	
	return ret;
}

//struct powerctrl Subsensor_PowerOn[SEQ_SIZE]={};
//struct powerctrl Subsensor_PowerOff[SEQ_SIZE]={};
struct powerctrl Ovxx_mipiraw_PowerOn[] = {
	{MPOWER_DOWN_PIN		, 0, 			0},
	{MRESET_PIN					, 0, 			10},
	{IOVDD_PIN						, 1800, 		10},
	{AVDD_PIN						, 2800, 		10},
	{DVDD_PIN						, 1200, 		10},
	{AF_PIN							, 2800, 		10},
	{MPOWER_DOWN_PIN		, 1, 			5},
	{MRESET_PIN					, 1, 			5},
	{SPOWER_DOWN_PIN		, 0, 			5},
	{SRESET_PIN					, 0, 			5},
	{SEQ_END						, 0, 			0}
};

struct powerctrl Ovxx_mipiraw_PowerDown[] = {
	{MPOWER_DOWN_PIN		, 1, 			10},
	{MRESET_PIN					, 1, 			10},
	{DVDD_PIN						, 0, 			10},
	{AVDD_PIN						, 0, 			0},
	{IOVDD_PIN						, 0, 			5},
	{AF_PIN							, 0, 			0},
	{MPOWER_DOWN_PIN		, 0, 			0},
	{MRESET_PIN					, 0, 			0},
	{SEQ_END						, 0, 			0}
};


int Mainseq_to_subseq(struct powerctrl *despower, struct powerctrl *srcpower)
{
	int i = 0;

	if (!srcpower)
		return -1;

	while(i < SEQ_SIZE) {
		despower[i].pwtype = srcpower[i].pwtype;
		despower[i].voltage = srcpower[i].voltage;
		despower[i].nms= srcpower[i].nms;
		i++;
	}
	i=0;
	
	while (despower[i].pwtype != SEQ_END) {
		if (despower[i].pwtype == MPOWER_DOWN_PIN)
			despower[i].pwtype == SPOWER_DOWN_PIN;
		else if (despower[i].pwtype == MRESET_PIN)
			despower[i].pwtype == SRESET_PIN;
		else if (despower[i].pwtype == SPOWER_DOWN_PIN)
			despower[i].pwtype == MPOWER_DOWN_PIN;
		else if (despower[i].pwtype == SRESET_PIN)
			despower[i].pwtype == MRESET_PIN;
		i++;
	}
	return 0;
}

int kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On, char* mode_name)
{
	int set_default_value=0;
	struct power_seq *seq = NULL;
	struct powerctrl *power;
	 int index = 0;
	 

	
	u32 pinSetIdx = 0;//default main sensor

	seq = get_camera_power_seq(currSensorName, SensorIdx);
	if (!seq) {
		printk("[@@debug]: seq error!\n");

		if(1) {
			if (SensorIdx == DUAL_CAMERA_MAIN_SENSOR) {
				
				Main_DefaultModulePower[0].name=currSensorName;
				Main_DefaultModulePower[1].name=list_end;
				Main_DefaultModulePower[0].ftype=FT_AF;
				Main_DefaultModulePower[1].ftype=FT_AF;
				Main_DefaultModulePower[0].pwon=Ovxx_mipiraw_PowerOn;
				Main_DefaultModulePower[0].pwoff=Ovxx_mipiraw_PowerDown;
				Main_DefaultModulePower[1].pwon=NULL;
				Main_DefaultModulePower[1].pwoff=NULL;
				seq = Main_DefaultModulePower;
				//goto _kdCISModulePowerOn_exit_;
				//seq = Sub_DefaultModulePower;
				//seq->pwon = Ovxx_mipiraw_PowerOn;
				//seq->pwoff = Ovxx_mipiraw_PowerDown;
			}
			else if (SensorIdx == DUAL_CAMERA_SUB_SENSOR) {
				Mainseq_to_subseq(Sub_camera_DefaultPowerOn, Ovxx_mipiraw_PowerOn);
				Mainseq_to_subseq(Sub_camera_DefaultPowerOff, Ovxx_mipiraw_PowerDown);

				Sub_DefaultModulePower[0].name=currSensorName;
				Sub_DefaultModulePower[1].name=list_end;
				Sub_DefaultModulePower[0].ftype=FT_AF;
				Sub_DefaultModulePower[1].ftype=FT_AF;
				Sub_DefaultModulePower[0].pwon=Sub_camera_DefaultPowerOn;
				Sub_DefaultModulePower[0].pwoff=Sub_camera_DefaultPowerOff;
				Sub_DefaultModulePower[1].pwon=NULL;
				Sub_DefaultModulePower[1].pwoff=NULL;	
				
				//Sub_DefaultModulePower[0].pwon = Sub_camera_DefaultPowerOn;
				//Sub_DefaultModulePower[0].pwoff = Sub_camera_DefaultPowerOff;
				seq = Sub_DefaultModulePower;
			}			
		}
		
		//return -1;
	}
/*
	if((!set_default_value)&&(SensorIdx==DUAL_CAMERA_MAIN_SENSOR)) {
      	seq = Main_ModulePower;
    } else if((!set_default_value)&&(SensorIdx==DUAL_CAMERA_SUB_SENSOR))	 {
      	seq = Sub_ModulePower;
    }	else if(set_default_value==0) {
    	//seq = ModulePower;
    }*/

    if (DUAL_CAMERA_MAIN_SENSOR == SensorIdx){
        pinSetIdx = 0;
		 //goto _kdCISModulePowerOn_exit_;
    } else if (DUAL_CAMERA_SUB_SENSOR == SensorIdx) {
        pinSetIdx = 1;
		//goto _kdCISModulePowerOn_exit_;
    } else if (DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx) {
        pinSetIdx = 2;
		goto _kdCISModulePowerOn_exit_;
    }

	ISP_MCLK1_EN(1); 

	if(currSensorName)
	{
		//PK_DBG("[@@debug] kdCISModulePowerOn: find the camera index: %d\n", i);
		if(On)
		{
			power = seq->pwon;
			printk("[@@debug] kdCISModulePowerOn: power[%d].pwtype = %d\n", index, power[index].pwtype);
			while(power[index].pwtype != SEQ_END) 
			{
				printk("[@@debug] power[index].pwtype  = %d\n", power[index].pwtype);
				if(TRUE != kdPinPowerCtrl(pinSetIdx, &power[index], TRUE, mode_name)) 
				{
					printk("[@@debug][CAMERA SENSOR] Fail to control IO power\n");
					goto _kdCISModulePowerOn_exit_;
				}
				index++;
			}
		} 
		else 
		{
			power = seq->pwoff;
			printk("[@@debug] kdCISModulePowerOn: power[%d].pwtype = %d\n", index, power[index].pwtype);
			while(power[index].pwtype != SEQ_END) 
			{
				printk("[@@debug] power[index].pwtype  = %d\n", power[index].pwtype);
				if(TRUE != kdPinPowerCtrl(pinSetIdx, &power[index], TRUE, mode_name)) 
				{
					printk("[@@debug][CAMERA SENSOR] Fail to control IO power\n");
					goto _kdCISModulePowerOn_exit_;
				}
				index++;
			}
		}
}

    return 0;

_kdCISModulePowerOn_exit_:
    return -EIO;

}

EXPORT_SYMBOL(kdCISModulePowerOn);

